package znet

import (
	"fmt"
	"github.com/spf13/cast"
	"strconv"
	"zinxLearn/pkg/zinx/util"
	"zinxLearn/pkg/zinx/ziface"
)

type ZMsgHandler struct {
	Apis           map[uint32]ziface.IRouter // 存放每个MsgId 所对应的处理方法的map属性
	WorkerPoolSize uint32                    // 业务工作Worker池的数量
	TaskQueue      []chan ziface.IRequest    // Worker负责取任务的消息队列
}

func NewZMsgHandle() *ZMsgHandler {
	return &ZMsgHandler{
		Apis:           make(map[uint32]ziface.IRouter),
		WorkerPoolSize: util.WorkerPoolSize,
		TaskQueue:      make([]chan ziface.IRequest, util.WorkerPoolSize),
	}
}
func (m *ZMsgHandler) Do(request ziface.IRequest) {
	handler, ok := m.Apis[request.ZData().GetMsgID()]
	if !ok {
		fmt.Println("api msgId = ", request.ZData().GetMsgID(), " is not FOUND!")
		return
	}

	//执行对应处理方法
	handler.PreHandle(request)
	handler.Handle(request)
	handler.PostHandle(request)
}
func (m *ZMsgHandler) AddRouter(msgID uint32, router ziface.IRouter) {
	//1 判断当前msg绑定的API处理方法是否已经存在
	if _, ok := m.Apis[msgID]; ok {
		panic("repeated api , msgId = " + strconv.Itoa(int(msgID)))
	}
	//2 添加msg与api的绑定关系
	m.Apis[msgID] = router
	fmt.Println("Add api msgId = ", msgID)
}
func (m *ZMsgHandler) StartWorkerPool() {
	for i := 0; i < int(m.WorkerPoolSize); i++ {
		m.TaskQueue[i] = make(chan ziface.IRequest, util.MaxWorkerTaskLen)
		go m.StartOneWorker(i, m.TaskQueue[i])
	}
}
func (m *ZMsgHandler) SendMsgToTaskQueue(request ziface.IRequest) {
	// 1. 根据Conn的ID来分配的连接应该由哪个worker来负责处理
	// 2.轮询平均分配

	// 得到需要处理此条连接的workID
	workerID := request.ZConn().GetConnID() % m.WorkerPoolSize
	m.TaskQueue[workerID] <- request // 将消息发送到任务队列
}
func (m *ZMsgHandler) StartOneWorker(workID int, taskQueue chan ziface.IRequest) {
	fmt.Println("Worker ID = ", workID, " is started.")
	for {
		select {
		case req := <-taskQueue:
			m.Do(req)

		}
	}
}
func (m *ZMsgHandler) Size() int {
	return cast.ToInt(m.WorkerPoolSize)
}
